package com.fingard.csp.listener;

import com.fingard.csp.common.log.LogHelper;
import com.fingard.csp.common.text.StringHelper;
import com.fingard.csp.service.socket.SocketMessageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.env.Environment;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Slf4j
public class SocketServerThread extends Thread {
    public Environment env;
    public SocketMessageService socketMsgService;

    /**
     * Socket服务器
     */
    private ServerSocket serverSocket;

    /**
     * 任务线程池
     */
    private ExecutorService threadPool = Executors.newCachedThreadPool();

    /**
     * Socket侦听服务初始化
     *
     */
    public SocketServerThread(Environment env, SocketMessageService socketMsgService) {
        this.env = env;
        this.socketMsgService = socketMsgService;

        try {
            log.info("开始启动Socket侦听服务...");
            if (serverSocket == null) {
                String listenerPort = env.getProperty("listener.port");
                if (StringHelper.hasAnyChar(listenerPort)) {
                    log.info("Socket侦听服务绑定端口：" + listenerPort);
                    serverSocket = new ServerSocket(Integer.parseInt(listenerPort));
                    log.info("Socket侦听服务已启动，等待客户端连接...\r\n\r\n");
                } else {
                    log.info("Socket侦听服务绑定端口未设置，暂不开启侦听!");
                }
            }
        } catch (Exception ex) {
            log.info("后台socket侦听服务启动失败,出错信息:\r\n" + LogHelper.getStackTrace(ex));
        }
    }

    /**
     * Socket客户端请求信息处理
     */
    @Override
    public void run() {
        while (!this.isInterrupted()) {
            try {
                Socket socket = serverSocket.accept();
                Runnable runnable = () -> {
                    dealMessage(socket);
                };
                threadPool.submit(runnable);
            } catch (IOException ex) {
                log.info("接收客户端请求信息处理失败,出错信息:\r\n" + LogHelper.getStackTrace(ex));
            }
        }
    }

    /**
     * Socket客户端消息处理
     *
     * @param socket
     */
    public void dealMessage(Socket socket) {
        InputStream inputStream = null;
        OutputStream outputStream = null;
        PrintWriter printWriter = null;

        try {
            log.info("-----------------------------------------------------------------------开始客户端消息处理-----------------------------------------------------------------------------------------------");
            log.info("客户端已连接,来源IP：" + socket.getInetAddress().getHostAddress());

            inputStream = socket.getInputStream();
            StringBuilder stringBuilder = new StringBuilder();
            byte[] bytes = new byte[1024];
            int len;
            while ((len = inputStream.read(bytes)) != -1) {
                stringBuilder.append(new String(bytes, 0, len, "GBK"));
                if (len < bytes.length) {
                    break;
                }
            }
            String requestMessage = stringBuilder.toString();
            log.info("接收客户端请求信息：\r\n" + requestMessage);
            String responseMessage = "";
            if(StringHelper.isNullOrEmpty(requestMessage)) {
                responseMessage = "客户端消息为空，请检查客户端问题!";
            } else {
                if (requestMessage.contains("<")) {
                    requestMessage = requestMessage.substring(requestMessage.indexOf("<"));
                }
                responseMessage = socketMsgService.dealRequest(requestMessage);
            }
            log.info("发送客户端响应信息:\r\n" + responseMessage);
            outputStream = socket.getOutputStream();
            printWriter = new PrintWriter(outputStream);
            printWriter.print(responseMessage);
            printWriter.flush();
            log.info("-----------------------------------------------------------------------客户端消息处理完毕-----------------------------------------------------------------------------------------------\r\n\r\n");
        } catch (Exception ex) {
            log.info("客户端消息处理失败，出错信息:\r\n" + LogHelper.getStackTrace(ex));
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (printWriter != null) {
                    printWriter.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
                if (socket != null && !socket.isClosed()) {
                    socket.shutdownOutput();
                    socket.close();
                }
            } catch (IOException ex) {
                log.info("接收客户端请求信息处理后Socket流关闭失败:\r\n" + LogHelper.getStackTrace(ex));
            }
        }
    }

    /**
     * Socket侦听服务关闭
     */
    public void closeSocketServer() {
        try {
            if (serverSocket != null && !serverSocket.isClosed()) {
                serverSocket.close();
            }
        } catch (IOException ex) {
            log.info("Socket侦听服务关闭失败:\r\n"+LogHelper.getStackTrace(ex));
        }
    }
}